#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : lei.wang
import time
from typing import Annotated
import jwt
from app.core.config import config
from fastapi import Request
from app.core.exceptions.http_exceptions import CustomException
from app.core.pkg.log import logger
from app.services.user import UserScoreService


JWT_TOKEN_EXPIRE_TIME = config.get('jwt').get('exp')  # token有效时间 2小时
JWT_SECRET = config.get('jwt').get('secret')  # 加解密密钥
JWT_ALGORITHM = config.get('jwt').get('algorithm')  # 加解密算法


def generate_jwt_token(user_id: str) -> str:
    """根据用户id生成token"""
    payload = {'user_id': user_id, 'exp': int(time.time()) + int(JWT_TOKEN_EXPIRE_TIME)}
    token = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
    return token


def refresh_jwt_token(expired_token: str) -> str:
    """刷新过期的token
    Args:
        expired_token: 过期的JWT token
    Returns:
        str: 新的JWT token
    """
    # 验证过期token，不检查过期时间
    payload = verify_jwt_token(expired_token, check_expiration=False)
    user_id = payload.get("user_id")
    
    # 生成新token
    new_token = generate_jwt_token(user_id)
    logger.info(f'刷新token成功: 用户ID={user_id}')
    return new_token


def verify_jwt_token(token: str, check_expiration: bool = True) -> dict:
    """验证用户token
    Args:
        token: JWT token
        check_expiration: 是否检查token过期时间
    Returns:
        dict: 包含user_id和exp的字典
    """
    try:
        _payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM], options={"verify_exp": check_expiration})
    except jwt.ExpiredSignatureError:
        logger.warning('token已失效')
        if check_expiration:
            raise CustomException(status_code=401, detail="token过期")
        # 如果不检查过期，则继续解析
        _payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM], options={"verify_exp": False})
    except jwt.PyJWTError:
        logger.error('token解析失败')
        raise CustomException(status_code=401, detail="token解析失败")
    
    logger.info(f'token解析成功: {_payload}')
    user_id = _payload.get('user_id')
    exp = _payload.get('exp')
    return {"user_id": user_id, "exp": exp}


def validate_auth_header(request: Request):
    """验证请求头中的token"""
    if not config.get('need_auth'):
        return True
    headers_token = request.headers.get('Authorization')
    # Bearer token
    if headers_token:
        if 'Bearer' not in headers_token:
            raise CustomException(status_code=401, detail="Bearer token 格式错误")
        token = headers_token.split(' ')[1]
        if not token:
            raise CustomException(status_code=401, detail="未授权")
        result = verify_jwt_token(token)
        return result["user_id"]
    else:
        raise CustomException(status_code=401, detail="未授权")


async def validate_user_score(payload_id: str, db):
    """ 验证用户积分 """
    try:
        user_score = await UserScoreService(db).get_user_score(payload_id)
        if not user_score:
            logger.error(f"用户({payload_id})积分记录不存在")
            raise CustomException(status_code=400, detail="用户积分记录不存在，请联系客服")
            
        remaining_score = user_score.get('total_score', 0) - user_score.get('used_score', 0)
        ask_cost = config.get('score').get('ask_question')
        
        logger.info(f"用户({payload_id})当前积分: 总积分={user_score.get('total_score', 0)}, 已用={user_score.get('used_score', 0)}, 剩余={remaining_score}")
        
        if remaining_score <= 0:
            raise CustomException(status_code=400, detail="积分不足,请先购买积分")
        elif remaining_score < ask_cost:
            raise CustomException(status_code=400, detail="积分不足,请先购买积分")
    except CustomException:
        # 直接抛出自定义异常
        raise
    except Exception as e:
        logger.error(f"验证用户({payload_id})积分时出错: {str(e)}")
        raise CustomException(status_code=500, detail="验证用户积分时出错")
